package LinkList;


public class SingleLinkList<E> {

    SingleLinkNode<E> head = null;

    SingleLinkNode<E> foot = null;

    int size = 0;

    public void add(E element) {
        SingleLinkNode node = new SingleLinkNode(element, null);
        if (this.head == null) {
            this.head = node;
        }
        if (this.foot != null) {
            SingleLinkNode oldFoot = this.foot;
            oldFoot.nextNode = node;
        }
        foot = node;
        this.size += 1;
    }

    public void insert(E element, int index) {
        if (index == this.size) {
            add(element);
        }else {
            if (index == 0) {
                SingleLinkNode node = new SingleLinkNode(element, this.head);
                this.head = node;
            }else {
                SingleLinkNode preNode = findNode(index - 1);
                SingleLinkNode node = new SingleLinkNode(element, preNode.nextNode);
                preNode.nextNode = node;
            }
            this.size += 1;
        }
    }

    public E removeLast() {
        if (this.foot == null) {
            return null;
        }
        SingleLinkNode<E> oldFoot = foot;
        if (this.size == 1) {
            this.foot = null;
            this.head = null;
        }else {
            this.foot = this.findNode(this.size - 2);
            this.foot.nextNode = null;
        }
        this.size -= 1;
        return oldFoot.value;
    }

    public E removeFirst() {
        if (this.head == null) {
            return null;
        }
        SingleLinkNode<E> oldHead = this.head;
        if (this.size == 1) {
            this.head = null;
            this.foot = null;
        }else {
            this.head = this.head.nextNode;
        }
        this.size -= 1;
        return oldHead.value;
    }

    public E remove(int index) {
        if (index == 0) {
            return this.removeFirst();
        }
        if (index + 1 == this.size) {
            return this.removeLast();
        }
        SingleLinkNode<E> node = null;
        node = this.findNode(index - 1);
        node.nextNode = node.nextNode.nextNode;
        this.size -= 1;
        return node.value;
    }

    public E first() {
        if (this.head == null) {
            return null;
        }
        return this.head.value;
    }

    public E last() {
        if (this.foot == null) {
            return null;
        }
        return this.foot.value;
    }

    public int size() {
        return this.size;
    }

    public boolean isEmpty() {
        return this.size == 0 ? true : false;
    }

    private SingleLinkNode findNode(int index) {
        if (index >= this.size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size : " + this.size);
        }
        SingleLinkNode node = this.head;
        while (index > 0) {
            node = node.nextNode;
            index -= 1;
        }
        return node;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        SingleLinkNode node = head;
        while (node != null) {
            sb.append("-").append(node.value);
            node = node.nextNode;
        }
        sb.append("-").append(foot.value);
        return sb.toString();
    }
}

class SingleLinkNode<E> {

    E value;

    SingleLinkNode nextNode;

    public SingleLinkNode(E value, SingleLinkNode nextNode) {
        this.value = value;
        this.nextNode = nextNode;
    }

}
